package tcp_proxy_middleware

import (
	"fmt"

	"github.com/afex/hystrix-go/hystrix"
	"github.com/youkelike/gateway/core/log"
	"github.com/youkelike/gateway/dao"
	"github.com/youkelike/gateway/tcp_server"
)

func TcpCircuitBreakMiddleware() func(c *tcp_server.TcpSliceRouterContext) {
	return func(c *tcp_server.TcpSliceRouterContext) {
		serverInterface := c.Get("service")
		if serverInterface == nil {
			c.Conn.Write([]byte("get service empty"))
			c.Abort()
			return
		}
		serviceDetail := serverInterface.(*dao.ServiceDetail)

		if serviceDetail.CircuitConfig.NeedCircuit == 1 {
			hystrix.Do(serviceDetail.Info.ServiceName, func() (err error) {
				defer func() {
					// 通过捕获 panic 来感知下游 lb 地址为空或者连接失败，
					// 连接关闭不在这里处理，
					// 而且对于 tcp 长连接要给 hystrix 配置超长的 timeout 时间
					if e := recover(); e != nil {
						remoteAddr := c.Conn.RemoteAddr().String()
						log.Error("tcp: panic serving %v: %v", remoteAddr, e)
						fmt.Println("hystrix panic<<<<<")
						err = fmt.Errorf("%v", e)
					}
				}()

				c.Next()

				return
			}, func(err error) error {
				if err != nil {
					fmt.Println("hystrix error<<<<<", err)
					c.Conn.Write([]byte("error closed"))
					return nil
				}
				return nil
			})
			return
		}

		c.Next()
	}
}
